﻿namespace CookieTerm
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public class SelectionManager
    {
        private IWindow window;
        private Controller controller;
        private int rows, columns;
        private bool hasSelection;
        private ConsoleCell selectionStart;
        private ConsoleCell selectionEnd;

        public SelectionManager(IWindow window, Controller controller)
        {
            this.window = window;
            this.controller = controller;
            this.rows = this.controller.Rows;
            this.columns = this.controller.Columns;
        }

        public void SelectAll()
        {
            StartTextSelection(1, 1);
            ExtendTextSelectionTo(rows, columns);
        }

        public void StartTextSelection(int row, int column)
        {
            ConsoleCell p = new ConsoleCell(columns, row, column);
            StartTextSelection(p);
        }

        public void StartTextSelection(ConsoleCell p)
        {
            this.hasSelection = true;
            this.selectionStart = p;
            this.selectionEnd = p;

            this.window.InvalidateCell(p.Row, p.Column);
        }

        public void ExtendTextSelectionTo(int row, int column)
        {
            ConsoleCell p = new ConsoleCell(columns, row, column);
            this.ExtendTextSelectionTo(p);
        }

        public void ExtendTextSelectionTo(ConsoleCell p)
        {
            if (p != this.selectionEnd)
            {
                ConsoleCell min = ConsoleCell.Min(this.selectionEnd, p);
                ConsoleCell max = ConsoleCell.Max(this.selectionEnd, p);

                this.selectionEnd = p;

                for (ConsoleCell c = min; c < max; c++)
                {
                    this.window.InvalidateCell(c.Row, c.Column);
                }
            }
        }

        public string GetSelectedText(bool wrapLine)
        {
            if (this.hasSelection)
            {
                ConsoleCell min = ConsoleCell.Min(this.selectionStart, this.selectionEnd);
                ConsoleCell max = ConsoleCell.Max(this.selectionStart, this.selectionEnd);

                StringBuilder text = new StringBuilder();

                for (ConsoleCell c = min; c <= max; c++)
                {
                    char ch = this.controller.VideoBuffer[c.Row, c.Column].Character;
                    if (ch != 0)
                    {
                        text.Append(this.controller.VideoBuffer[c.Row, c.Column].Character);
                    }

                    if (wrapLine && c.Column == this.columns)
                    {
                        text.Append("\r\n");
                    }
                }

                return text.ToString();
            }
            else
            {
                return string.Empty;
            }
        }

        public bool IsSelected(int row, int column)
        {
            if (this.hasSelection)
            {
                ConsoleCell p = new ConsoleCell(this.columns, row, column);
                return (p >= this.selectionStart && p <= this.selectionEnd) || (p >= this.selectionEnd && p <= this.selectionStart);
            }
            else
            {
                return false;
            }
        }

        public void ClearTextSelection()
        {
            if (this.hasSelection)
            {
                this.hasSelection = false;

                ConsoleCell min = ConsoleCell.Min(this.selectionStart, this.selectionEnd);
                ConsoleCell max = ConsoleCell.Max(this.selectionStart, this.selectionEnd);

                for (ConsoleCell c = min; c <= max; c++)
                {
                    this.window.InvalidateCell(c.Row, c.Column);
                }
            }
        }
    }
}
